package cn.hcbycloud.auth.service;

import cn.hcbycloud.auth.bo.LoginSuccessResultBO;
import cn.hcbycloud.auth.bo.UserInfoBO;
import cn.hcbycloud.auth.mapper.UserLoginMapper;
import cn.hcbycloud.auth.model.UserLogin;
import cn.hcbycloud.common.core.constant.CustStatusTypeEnum;
import cn.hcbycloud.common.core.exception.CustomizeException;
import cn.hcbycloud.common.core.utils.ObjectUtils;
import cn.hcbycloud.common.core.utils.PasswordUtil;
import cn.hcbycloud.common.jwt.constant.TokenTypeEnum;
import cn.hcbycloud.common.jwt.service.encryptionkey.BaseGenerateJwtKeyService;
import cn.hcbycloud.common.jwt.service.jwt.JwtBuilderFactory;
import cn.hcbycloud.common.jwt.service.jwt.JwtRedisCacheService;
import cn.hcbycloud.common.jwt.service.jwt.JwtService;
import cn.hcbycloud.common.jwt.vo.JwtToken;
import cn.hcbycloud.common.jwt.vo.LoginInfo;
import cn.hcbycloud.common.mvc.model.AppTenant;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 用户认证信息表
 *
 * @author gaoheng
 * @date 2022-01-19 00:12:02
 */
@Service
@AllArgsConstructor
public class UserLoginService extends ServiceImpl<UserLoginMapper, UserLogin> {
    private UserLoginMapper userLoginMapper;
    private TenantService tenantService;
    /**
     * JWTToken 生成服务
     */
    private JwtService jwtService;
    /**
     * 密钥对
     */
    private BaseGenerateJwtKeyService generateJwtKeyService;
    /**
     * JWT 构造器
     */
    private JwtBuilderFactory jwtBuilder;

    /**
     * JWT令牌对象缓存服务
     */
    private JwtRedisCacheService jwtRedisCacheService;

    /**
     * 判断用户是否存在
     *
     * @param userName
     * @return
     */
    public UserInfoBO getUserInfoByUserName(String userName, String tenantId) {
        return userLoginMapper.selectUserInfoByUserName(userName,tenantId);
    }


    /**
     * 根据用户名称获取用户详细信息列表
     * @param userNameList
     * @param tenantId
     * @return
     */
    public List<UserInfoBO> getUserInfoByUserNameList(List<String> userNameList,String tenantId) {
        return userLoginMapper.selectUserInfoByUserNameList(userNameList,tenantId);
    }

    /**
     * @param userLoginList
     */
    public void addUserLoginInfo(List<UserLogin> userLoginList, String userId) {
        List<UserLogin> list = CollUtil.newArrayList();
        userLoginList.forEach(item -> {
            UserLogin userLogin = new UserLogin();
            userLogin.preInsert();
            userLogin.setUserId(userId);
            userLogin.setUserName(item.getUserName());
            userLogin.setUserNameType(item.getUserNameType());
            list.add(userLogin);
        });
        if (CollUtil.isNotEmpty(list)) {
            this.saveBatch(list);
        }
    }

    /**
     * 认证校验通过后，该方法将token进行返回
     * @param userName
     * @return
     */
    public LoginSuccessResultBO getJwtToken(String userName, String password,String tenantCode) {
        // 获取租户信息
        AppTenant tenant = tenantService.getTenantByRequireCode(tenantCode);
        UserInfoBO userInfoBo = this.getUserInfoByUserName(userName,tenant.getTenantId());
        /** 将传入的密码进行MD5加密与数据库中的密码进行比较 */
        String passwordParam = PasswordUtil.getMd5(password,userInfoBo.getSalt());
        if(!StrUtil.equals(passwordParam,userInfoBo.getPassword())) {
            throw new CustomizeException("登录密码错误");
        }
        LoginInfo loginInfo = new LoginInfo(userInfoBo.getUserId(), userInfoBo.getCustId(),
                tenant.getTenantId(), TokenTypeEnum.USER_TYPE.getType());
        // 如果用户对应的客户为禁用状态，则将loginInfo中的客户ID置为""
        if(StrUtil.equals(userInfoBo.getStatus(), CustStatusTypeEnum.STATUS_TYPE_DISABLE.getCode())) {
            loginInfo = new LoginInfo(userInfoBo.getUserId(), "",
                    tenant.getTenantId(),TokenTypeEnum.USER_TYPE.getType());
        }
        // 生成JWTToken对象
        JwtToken jwtToken = jwtService.generateToken(loginInfo, generateJwtKeyService, jwtBuilder);
        // 将JWT令牌存入缓存
        jwtRedisCacheService.setTokenToCache(jwtToken);
        LoginSuccessResultBO loginSuccessResultBo = ObjectUtils.cloneObj(userInfoBo,LoginSuccessResultBO.class);
        JwtToken token =  jwtRedisCacheService.getTokenFromCache(jwtToken);
        loginSuccessResultBo.setJwtToken(token.getToken());
        return loginSuccessResultBo;
    }
}
